/*
 * Copyright (c) 2022 Queclink-C-Library
 *
 * This file is subject to the terms and conditions of the MIT License.
 * For details, please see the LICENSE file or visit the MIT website: https://mit-license.org/
 */

#include <ctype.h>
#include <stddef.h>
#include <string.h>

#include <qlibc/assert.h>

#include "qlibc_log.h"
char *quec_memcasestr(const void *buf, size_t n, const char *str)
{
    assert(NULL != buf);
    assert(NULL != str);
    assert(0 < n);

    size_t i, j;
    char *start = (char*)buf;
    size_t len_str = strlen(str);

    if (n < len_str || 0 == len_str)
        return NULL;

    for (i = 0; i <= n - len_str; i++) {
        for (j = 0; j < len_str; j++) {
            if (start[i + j] != tolower(str[j]) &&
                start[i + j] != toupper(str[j]))
                break;
        }

        if (j >= len_str)
            return &start[i];
    }

    return NULL;
}

char *quec_memstr(const void *buf, size_t n, const char *str)
{
    assert(NULL != buf);
    assert(NULL != str);
    assert(0 < n);

    size_t i;
    size_t len = strlen(str);

    for (i = 0; i < n; i++) {
        if ((*((char *)buf + i) == *str) &&
            (!memcmp((char *)buf + i, str, len)) &&
            (i + len <= n))
            return (char *)buf + i;
    }

    return NULL;
}

size_t quec_memtrim(void *buf, size_t n)
{
    assert(NULL != buf);
    assert(0 < n);

    size_t i;
    size_t start_len, end_len;
    char *start = (char*)buf;

    for (i = 0; i < n; i++) {
        if (0 == isspace((int)start[i]) &&
            0 == iscntrl((int)start[i]))
            break;
    }

    start_len = i;

    for (i = n - 1; i > start_len; i--) {
        if (0 == isspace((int)start[i]) &&
            0 == iscntrl((int)start[i]))
            break;
    }

    end_len = n - i - 1;

    if (0 < start_len)
        memcpy(start, &start[start_len], n - (start_len + end_len));
    memset(&start[n - (start_len + end_len)], 0, start_len + end_len);

    return (n - start_len - end_len);
}


void *quec_memsrch(const void *buf, size_t n, const void *sbuf, size_t sn)
{
    assert(NULL != sbuf);
    assert(NULL != buf);
    assert(0 < sn);
    assert(0 < n);

    size_t i;

    if (n < sn)
        return NULL;

    for (i=0; i <= n-sn; i++) {
        if ((*((char *)buf+i) == *((char *)sbuf)) &&
            (!memcmp((char *)buf+i, sbuf, sn)))
            return (char *)buf+i;
    }

    return NULL;
}
